﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Windows;
using System.Windows.Forms;
using VNet.VisiSuite.Common;
using VNet.VisiSuite.Common.Resource;
using VNet.VisiSuite.Controls;
using VNet.VisiSuite.ExcelReader;
using VNet.VisiSuite.ExcelReader.ExcelReaderFactory;
using VNet.VisiSuite.ExcelReader.Models;
using VNet.VisiSuite.Service.Contact.Message.Base;
using VNet.VisiSuite.Service.Contact.Message.Item;
using VNet.VisiSuite.VisiAdmin.Common.Helpers;
using VNet.VisiSuite.VisiAdmin.Models;
using VNet.VisiSuite.VisiAdmin.Providers;
using VNet.VisiSuite.VisiAdmin.Views;
using MessageBox = System.Windows.MessageBox;

namespace VNet.VisiSuite.VisiAdmin.ViewModels
{
    public class ProductViewModel : BaseViewModel
    {
        #region Fields
        private ProductModel _cloneSelectedProduct;
        private ProductModel _selectedProduct;
        private ObservableCollection<ProductModel> _products;
        private ProductModel _pendingProduct;
        private VNetMenuItem _productMenuIcon;
        #endregion

        #region Constructors
        public ProductViewModel()
        {
            PageTitle = TitleString.ProductViewAdminTitle;

            TopRightButtonIcons = new ObservableCollection<VNetMenuItem> { new VNetMenuItem(null, "Add new product", CommonConstants.VNetIcon.AppbarListAdd, VNetMenuItemType.WhiteBackgroundTheme, OnAddNewProduct), };
            TopLeftButtonIcons = new ObservableCollection<VNetMenuItem> { new VNetMenuItem(null, "Return to previous screen", CommonConstants.VNetIcon.AppbarArrowLeft, VNetMenuItemType.WhiteBackgroundTheme, OnExit), };

            BottomMenuItems = new ObservableCollection<VNetMenuItem>();
            _productMenuIcon = new VNetMenuItem("Import Products", "Import Products", CommonConstants.VNetIcon.AppbarOfficeExcel, VNetMenuItemType.BlackBackgroundTheme, ImportProductsMenuClick);
            BottomMenuItems.Add(_productMenuIcon);

            SaveCommand = new RelayCommand(DoUpdateProduct);
            CancelCommand = new RelayCommand(DoCancel);
            DeleteCommand = new RelayCommand(DoDeleteProduct);

            Products = new ObservableCollection<ProductModel>();
        } 
        #endregion

        #region Properties

        public ObservableCollection<ProductModel> Products
        {
            get { return _products; }
            set
            {
                _products = value;
                OnPropertyChanged("Products");
            }
        }

        public ProductModel SelectedProduct
        {
            get { return _selectedProduct; }
            set
            {
                if (value != null && IsProductPendingChange(value))
                    return;

                //Must set to null to unhighlight the active item on UI
                _selectedProduct = null;
                OnPropertyChanged("SelectedProduct");

                //Continue the business logic
                _pendingProduct = null;
                _selectedProduct = value;
                if (_selectedProduct != null)
                {
                    CloneSelectedProduct = SmartReflection.CloneModel(_selectedProduct);
                    CloneSelectedProduct.ShouldValidate = true;
                }
                OnPropertyChanged("SelectedProduct");
            }
        }

        public ProductModel CloneSelectedProduct
        {
            get { return _cloneSelectedProduct; }
            set
            {
                _cloneSelectedProduct = value;
                OnPropertyChanged("CloneSelectedProduct");
            }
        }

        #endregion

        #region Methods

        private void ImportProductsMenuClick()
        {
            using (var openFileDialog = new OpenFileDialog())
            {
                openFileDialog.Filter = "Excel Files|*.xls;*.xlsx";
                openFileDialog.Title = "Select the product file to import.";
                if (openFileDialog.ShowDialog() == DialogResult.OK)
                {
                    try
                    {
                        var importers = new ExcelReaders();
                        var products = importers.GetProducts(openFileDialog.FileName);
                        MergeProducts(products);
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show(ex.Message);
                    }
                }
            }
        }

        private void MergeProducts(IExcelData products)
        {
            var productData = products as ProductData;
            if (productData != null && productData.Items != null)
            {
                var items = productData.Items.Select(item => new ProductItem
                    {
                        Sku = item.Sku,
                        Description = item.Description,
                        Revision = item.Revision,
                        Enabled = item.Enabled
                    }).ToList();
                IsBusy = true;
                DoAsync(ProductProviders.ImportProducts, ImportProductsCompleted, items);
            }
        }

        private void ImportProductsCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            var response = e.Result as SaveDataResponse<IList<ProductItem>>;
            IsBusy = false;
            if (response == null || !response.Success)
            {
                if (response != null)
                {
                    MessageBox.Show(response.Error.Description);
                }
                return;
            }
            if (IsClosing)
            {
                NavigateBack();
                return;
            }
            RefreshPage();
        }

        private void RefreshPage()
        {
            IsBusy = true;
            DoAsync(ProductProviders.GetProducts, GetProductsCompleted);
        }

        private void OnExit()
        {
            IsClosing = true;
            if (IsProductPendingChange(null))
                return;

            NavigateBack();
        }

        private void DoDeleteProduct(object obj)
        {
            ErrorMessage = null;
            if (MessageBox.Show(string.Format(FormatString.DeleteItemFormat, "product"), TitleString.ConfirmDeleteTitle, MessageBoxButton.YesNo) == MessageBoxResult.No)
                return;

            IsBusy = true;
            DoAsync(ProductProviders.DeleteProduct, DeleteProductCompleted, CloneSelectedProduct.ProductId);

            //Todo Implement Delete Product service
        }

        private void DoUpdateProduct(object obj)
        {
            if (!CloneSelectedProduct.IsValid())
                return;

            var productItem = new ProductItem
            {
                Sku = CloneSelectedProduct.Sku,
                Description = CloneSelectedProduct.Description,
                Revision = CloneSelectedProduct.Revision,
                Enabled = CloneSelectedProduct.IsEnabled,
                ProductId = CloneSelectedProduct.ProductId,
            };

            IsBusy = true;
            if (CloneSelectedProduct.IsAddNew)
                DoAsync(ProductProviders.InsertProduct, InsertProductCompleted, productItem);
            else
                DoAsync(ProductProviders.UpdateProduct, UpdateProductCompleted, productItem);
        }

        private void DoCancel(object obj)
        {
            CloneSelectedProduct = CloneSelectedProduct.IsAddNew ? null : SmartReflection.CloneModel(SelectedProduct);
        }

        private void OnAddNewProduct()
        {
            //Init new data for add new function
            SelectedProduct = new ProductModel { IsAddNew = true };
        }

        private void GetProductsCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            var response = e.Result as GetDataResponse<IList<ProductItem>>;
            if (response != null && response.Data != null)
            {
                var list = new ObservableCollection<ProductModel>();
                foreach (var product in response.Data)
                {
                    list.Add(ConvertItemToModel(product));
                }
                Products = list;
            }
            IsBusy = false;
        }

        private void DeleteProductCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            var response = e.Result as DeleteDataResponse;

            if (response == null || !response.Success)
            {
                IsBusy = false;
                if (response != null)
                {
                    CloneSelectedProduct.ErrorMessage = response.Error.Description;
                }
                _pendingProduct = null;
                IsClosing = false;
                return;
            }

            if (IsClosing)
            {
                IsBusy = false;
                NavigateBack();
                return;
            }

            CloneSelectedProduct = null;
            SelectedProduct = null;

            var item = Products.FirstOrDefault(t => t.ProductId == response.DataId);
            if (item != null)
                Products.Remove(item);
            IsBusy = false;
        }

        private void UpdateProductCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            var response = e.Result as SaveDataResponse<ProductItem>;
            IsBusy = false;

            if (response == null || !response.Success)
            {
                if (response != null)
                    CloneSelectedProduct.ErrorMessage = response.Error.Description;

                CloneSelectedProduct.IsCancelEnable = false;
                _pendingProduct = null;
                IsClosing = false;
                return;
            }

            if (IsClosing)
            {
                NavigateBack();
                return;
            }

            _selectedProduct.Sku = response.Data.Sku;
            _selectedProduct.Description = response.Data.Description;
            _selectedProduct.Revision = response.Data.Revision;
            _selectedProduct.ProductId = response.Data.ProductId;
            _selectedProduct.IsEnabled = response.Data.Enabled;
            _selectedProduct.LastUpdatedByUser = response.Data.LastUpdatedByUser;
            _selectedProduct.LastUpdatedDate = response.Data.LastUpdatedDate.ToString(FormatString.DateTimeFormat);
            
            _selectedProduct.IsChange = false;
            _selectedProduct.ErrorMessage = null;
            _selectedProduct.IsCancelEnable = false;
            CloneSelectedProduct = SmartReflection.CloneModel(SelectedProduct);
            if (_pendingProduct != null)
            {
                SelectedProduct = _pendingProduct;
                _pendingProduct = null;
            }
        }

        private void InsertProductCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            var response = e.Result as SaveDataResponse<ProductItem>;
            IsBusy = false;
            if (response == null || !response.Success)
            {
                if (response != null)
                {
                    CloneSelectedProduct.ErrorMessage = response.Error.Description;
                }
                _pendingProduct = null;
                IsClosing = false;
                return;
            }
            if (IsClosing)
            {
                NavigateBack();
                return;
            }

            var newModel = ConvertItemToModel(response.Data);

            Products.Add(newModel);
            CloneSelectedProduct = null;
            SelectedProduct = _pendingProduct ?? newModel;
            _pendingProduct = null;
        }

        private void NavigateBack()
        {
            NavigationManager.NavigateTo(new PlantView(), null);
        }

        private ProductModel ConvertItemToModel(ProductItem item)
        {
            if (item == null)
                return null;

            var model = new ProductModel
            {
                ProductId = item.ProductId,
                Sku = item.Sku,
                Description = item.Description,
                Revision = item.Revision,
                IsEnabled = item.Enabled,
                CreatedDate = item.CreatedDate.ToString(FormatString.DateTimeFormat),
                LastUpdatedDate = item.LastUpdatedDate.ToString(FormatString.DateTimeFormat),
                CreatedByUser = item.CreatedByUser,
                LastUpdatedByUser = item.LastUpdatedByUser,
            };
            return model;
        }

        public bool IsProductPendingChange(ProductModel value)
        {
            if (_cloneSelectedProduct != null && _cloneSelectedProduct.HasChange())
            {
                switch (ConfirmDialog.Show())
                {
                    case SaveChangesDialogResult.Discard:
                        return false;
                    case SaveChangesDialogResult.Save:
                        _pendingProduct = value;
                        DoUpdateProduct(null);
                        return true;
                    case SaveChangesDialogResult.Resume:
                        IsClosing = false;
                        _pendingProduct = null;
                        return true;
                }
            }
            return false;
        }

        #endregion

        #region Navigation Framework
        public override void OnNavigate(object obj)
        {
            IsBusy = true;
            DoAsync(ProductProviders.GetProducts, GetProductsCompleted);
        }

        public override void OnLeave()
        {
        }
        #endregion
    }
}
